package com.sip.stream.utils.zfy.encoder;

import android.media.MediaCodec;
import android.media.MediaCodecList;
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.Surface;

import com.sip.stream.utils.zfy.GSMediaSampleData;
import com.sip.stream.utils.zfy.consumer.IGSAudioEncoderConsumer;
import com.sip.stream.utils.zfy.consumer.IGSMediaObserver;
import com.sip.stream.utils.zfy.consumer.IGSWAVConsumer;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;

public class GSAACASyncEncoder extends AbstractMediaCodecEncoder implements IGSAudioEncoder, GSMediaCodecAsyncCallBack.GSMediaCodecAsyncCallBackListener {
    private static final String TAG = "GSAACASyncEncoder";

    private Handler backgroundHandler;
    private HandlerThread backgroundThread;
    private GSMediaCodecAsyncCallBack codecAsyncCallBack;
    private IGSMediaObserver<IGSWAVConsumer> observer;
    private int sampleRate;
    private ArrayList<IGSAudioEncoderConsumer> listeners = new ArrayList<>();
    private long lastAudioTimeStamp = 0;

    public GSAACASyncEncoder(int sampleRate, int channelCount, int bitrate) {
        this.sampleRate = sampleRate;
        if (setUpMediaCodec(sampleRate, channelCount, bitrate)) {
            Log.i(TAG, "create GSAACASyncEncoder success");
        } else {
            Log.e(TAG, "create GSAACASyncEncoder failed");
        }
    }

    private boolean setUpMediaCodec(int sampleRate, int channelCount, int bitrate) {
        MediaFormat createAudioFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", sampleRate, channelCount);
        createAudioFormat.setInteger("aac-profile", 2);
        createAudioFormat.setInteger("bitrate", bitrate);
        createAudioFormat.setInteger("channel-count", channelCount);
        createAudioFormat.setInteger("frame-rate", 25);
        createAudioFormat.setInteger("i-frame-interval", 1);
        if (channelCount > 1) {
            createAudioFormat.setInteger("channel-mask", 12);
        } else {
            createAudioFormat.setInteger("channel-mask", 16);
        }
        if (new MediaCodecList(1).findEncoderForFormat(createAudioFormat) == null) {
            Log.e(TAG, "findEncoderForFormat null");
            return false;
        }
        try {
            this.mediaCodec = MediaCodec.createEncoderByType("audio/mp4a-latm");
            try {
                this.mediaCodec.configure(createAudioFormat, null, null, 1);
            } catch (MediaCodec.CodecException e) {
                Log.i(TAG, "create GSAACASyncEncoder failed " + e.getLocalizedMessage());
                e.printStackTrace();
            }
            this.codecAsyncCallBack = new GSMediaCodecAsyncCallBack(this.mediaCodec, this, false);
            this.mediaCodec.setCallback(this.codecAsyncCallBack, getBackgroundHandler());
            this.mediaCodec.start();
            return true;
        } catch (IOException e2) {
            e2.printStackTrace();
            return false;
        }
    }

    private synchronized Handler getBackgroundHandler() {
        if (this.backgroundThread == null || this.backgroundHandler == null) {
            HandlerThread handlerThread = new HandlerThread(TAG);
            this.backgroundThread = handlerThread;
            handlerThread.start();
            this.backgroundHandler = new Handler(this.backgroundThread.getLooper());
        }
        return this.backgroundHandler;
    }

    @Override
    public void startEncode() {
        MediaCodec mediaCodec = this.mediaCodec;
    }

    @Override
    public void stopEncode() {
        Log.i(TAG, "stopEncode");
        this.isStop = true;
        this.codecAsyncCallBack.setStop(true);
        if (this.observer != null) {
            Log.i(TAG, "GSAACASyncEncoder onStop observer");
            this.observer.onStop(this);
        }
    }

    @Override
    public void onAudioStream(byte[] bArr, long j) {
        this.codecAsyncCallBack.encode(bArr, j);
    }

    @Override
    public void addObserver(IGSMediaObserver<IGSWAVConsumer> iGSMediaObserver) {
        this.observer = iGSMediaObserver;
    }

    @Override
    public void addLisener(IGSAudioEncoderConsumer iGSAudioEncoderConsumer) {
        if (iGSAudioEncoderConsumer == null) {
            return;
        }
        if (this.cacheOutputFormate != null) {
            iGSAudioEncoderConsumer.setOutputFormat(this.cacheOutputFormate);
        }
        iGSAudioEncoderConsumer.addObserver(this);
        this.listeners.add(iGSAudioEncoderConsumer);
    }

    @Override
    public void encodeVideoSuccess(ByteBuffer byteBuffer, MediaCodec.BufferInfo bufferInfo) {
        if (bufferInfo.presentationTimeUs - this.lastAudioTimeStamp < 0) {
            Log.e(TAG, "timeStamp error: " + bufferInfo.presentationTimeUs + " lastAudioTimeStamp: " + this.lastAudioTimeStamp);
            return;
        }
        this.lastAudioTimeStamp = bufferInfo.presentationTimeUs;
        Iterator<IGSAudioEncoderConsumer> it = this.listeners.iterator();
        while (it.hasNext()) {
            it.next().encodeAudioSuccess(GSMediaSampleData.createAudioSampleData(byteBuffer, bufferInfo));
        }
        if (bufferInfo.flags == 4) {
            stopMediaCodec();
        }
    }

    @Override
    public void setOutputFormat(MediaFormat mediaFormat) {
        this.cacheOutputFormate = mediaFormat;
        Iterator<IGSAudioEncoderConsumer> it = this.listeners.iterator();
        while (it.hasNext()) {
            it.next().setOutputFormat(this.cacheOutputFormate);
        }
    }

    @Override
    public void stopMediaCodec() {
        super.stopMediaCodec();
        Log.i(TAG, "stopMediaCodec");
    }

    @Override
    public void onStop(IGSAudioEncoderConsumer iGSAudioEncoderConsumer) {
        Log.i(TAG, "onStop " + iGSAudioEncoderConsumer);
        removeLisener(iGSAudioEncoderConsumer);
    }

    @Override
    public void removeLisener(IGSAudioEncoderConsumer iGSAudioEncoderConsumer) {
        this.listeners.remove(iGSAudioEncoderConsumer);
        if (this.listeners.isEmpty()) {
            stopEncode();
        }
    }
}
